package config

import (
	"errors"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"os"
	"strings"
)

type beef struct {
	Version                     string `yaml:"version"`
	Debug                       bool   `yaml:"debug"`
	Client_debug                bool   `yaml:"client_debug"`
	Crypto_default_value_length int    `yaml:"crypto_default_value_length"`
	Credentials                 struct {
		User   string `yaml:"user"`
		Passwd string `yaml:"passwd"`
	}
	Restrictions struct {
		Permitted_hooking_subnet []string `yaml:"permitted_hooking_subnet"`
		Permitted_ui_subnet      []string `yaml:"permitted_ui_subnet"`
		Api_attempt_delay        string   `yaml:"api_attempt_delay"`
	}
	Http struct {
		Debug               bool   `yaml:"debug"`
		Host                string `yaml:"host"`
		Port                string `yaml:"port"`
		Xhr_poll_timeout    int    `yaml:"xhr_poll_timeout"`
		Allow_reverse_proxy bool   `yaml:"allow_reverse_proxy"`
		Hook_file           string `yaml:"hook_file"`
		Hook_session_name   string `yaml:"hook_session_name"`
		Restful_api         struct {
			Allow_cors           bool   `yaml:"allow_cors"`
			Cors_allowed_domains string `yaml:"cors_allowed_domains"`
		}
		Websocket struct {
			Enable             bool  `yaml:"enable"`
			Port               int64 `yaml:"port"`
			Secure             bool  `yaml:"secure"`
			Secure_port        int64 `yaml:"secure_port"`
			Ws_poll_timeout    int   `yaml:"ws_poll_timeout"`
			Ws_connect_timeout int   `yaml:"ws_connect_timeout"`
		}
		Web_server_imitation struct {
			Enable    bool   `yaml:"enable"`
			Type      string `yaml:"type"`
			Hook_404  bool   `yaml:"hook_404"`
			Hook_root bool   `yaml:"hook_root"`
		}
		Https struct {
			Enable bool   `yaml:"enable"`
			Key    string `yaml:"key"`
			Cert   string `yaml:"cert"`
		}
	}
	Database struct {
		File string `yaml:"file"`
	}
	Autorun struct {
		Result_poll_interval   int  `yaml:"result_poll_interval"`
		Result_poll_timeout    int  `yaml:"result_poll_timeout"`
		Continue_after_timeout bool `yaml:"continue_after_timeout"`
	}
	Dns_hostname_lookup bool `yaml:"dns_hostname_lookup"`
	Geoip               struct {
		Enable   bool   `yaml:"enable"`
		Database string `yaml:"database"`
	}
	Integration struct {
		Phishing_frenzy struct {
			Enable bool `yaml:"enable"`
		}
	}
	Extension struct {
		Admin_ui struct {
			Enable    bool   `yaml:"enable"`
			Base_path string `yaml:"base_path"`
		}
		Demos struct {
			Enable bool `yaml:"enable"`
		}
		Events struct {
			Enable bool `yaml:"enable"`
		}
		Evasion struct {
			Enable bool `yaml:"enable"`
		}
		Requester struct {
			Enable bool `yaml:"enable"`
		}
		Proxy struct {
			Enable bool `yaml:"enable"`
		}
		Network struct {
			Enable bool `yaml:"enable"`
		}
		Metasploit struct {
			Enable bool `yaml:"enable"`
		}
		Social_engineering struct {
			Enable bool `yaml:"enable"`
		}
		Xssrays struct {
			Enable bool `yaml:"enable"`
		}
	}
}

type Config struct {
	BeefConf beef `yaml:"beef"`
}

//数组转化为切片
func slice_To_Map(s_key []string, s_value []string) map[string]string {
	mapObj := map[string]string{}
	for s_key_index := range s_key {
		mapObj[s_key[s_key_index]] = s_value[s_key_index]
	}
	return mapObj
}

/*
待添加config参数，现在默认从头开始
*/
func Get(key string) (bool, string) {
	var subhash []string
	subkeys := strings.Split(key, ".")
	lastkey := subkeys[len(subkeys)-1]
	if len(subkeys) > 0 {
		subkeys = subkeys[:len(subkeys)-1]
	}
	for _, hash := range subkeys {
		subhash = append(subhash, hash)
	}
	subhash_map := slice_To_Map(subkeys, subhash)
	if subhash_map == nil {
		return false, ""
	} else if _, ok := subhash_map[lastkey]; ok {
		return true, subhash_map[lastkey]
	} else if _, ok := subhash_map[lastkey]; !ok {
		return false, ""
	}
}

//元素是否在数组内
//func IsContain(items []string, item string) bool {
//	for _, eachItem := range items {
//		if eachItem == item {
//			return true
//		}
//	}
//	return false
//}

func (c *Config) Parse(path string) (*Config, error) {
	configFile, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	// check file existence
	if _, existErr := os.Stat(path); existErr != nil && os.IsNotExist(existErr) {
		return nil, errors.New("config file does not exist at " + path)
	}
	// parse file
	err = yaml.Unmarshal(configFile, c)
	if err != nil {
		return nil, errors.New("config file cannot be parsed, check your syntax ")
	}
	return c, err
}

func (c *Config) Validate() error {
	return nil
}
